use std::collections::HashMap;
use std::error::Error;
use std::hash::Hash;
use std::io::{stdout, Write};
use std::net::Ipv4Addr;
use serde::{Serialize, Deserialize};
use serde_json::Value;
use crate::lincni::convertion::DNS;

#[derive(Clone,Debug)]
pub enum ErrorType {
    ErrUnknown,
    ErrIncompatibleCNIVersion,
    ErrUnsupportedField,
    ErrUnknownContainer,
    ErrInvalidEnvironmentVariables,
    ErrIOFailure,
    ErrDecodingFailure,
    ErrInvalidNetworkConfig,
    ErrTryAgainLater,
    ErrInternal,
    ErrUserOperator
}

impl Default for ErrorType {
    fn default() -> Self {
        ErrorType::ErrUnknown
    }
}

#[derive(Debug,Default,Serialize,Deserialize,Clone)]
pub struct ErrorResponse {
    #[serde(skip_serializing,skip_deserializing)]
    pub code:ErrorType,
    pub msg:String,
    pub details:String,
}

impl ErrorResponse {
    pub fn new(code:ErrorType,msg:String,details:String) -> Self {
        ErrorResponse{
            code,
            msg,
            details,
        }
    }

    pub fn error(&self) -> String {
        let mut details = String::new();
        if self.details.len() >  0 {
            details = format!(";{}",self.details);
        }
        format!("{}{}",self.msg,details)
    }

    pub fn print(&self) -> Result<(),Box<dyn Error>> {
        pretty_print(self.clone())
    }
}

fn pretty_print<T>(data:T) -> Result<(),Box<dyn Error>> where T:Serialize {
    let str = serde_json::to_string(&data)?;
    stdout().write(str.as_bytes())?;

    Ok(())
}

#[derive(Clone,Debug,Default,Serialize,Deserialize)]
pub struct NetConfig {
    #[serde(rename="cniVersion",skip_serializing_if = "Option::is_none",default)]
    pub cni_version:Option<String>,
    #[serde(skip_serializing_if = "Option::is_none",default)]
    pub name:Option<String>,
    #[serde(rename="type",skip_serializing_if = "Option::is_none",default)]
    pub typ:Option<String>,
    #[serde(rename="type",skip_serializing_if = "Option::is_none",default)]
    pub capabilities:Option<HashMap<String,bool>>,
    #[serde(skip_serializing_if = "Option::is_none",default)]
    pub ipam:Option<IPAM>,
    #[serde(skip_serializing_if = "Option::is_none",default)]
    pub dns:Option<DNS>,
    #[serde(rename="prevResult",skip_serializing_if = "Option::is_none",default)]
    pub prev_result:Option<Value>,
}

#[derive(Clone,Debug,Default,Serialize,Deserialize)]
pub struct IPAM {
    #[serde(rename="type")]
    pub typ:String,
}










